iT邦幫忙

0

JavaScript 中的 this

  • 分享至 

  • xImage
  •  

JavaScript 中的 this

🔹 this 是什麼?

this 是 JavaScript 中的一個關鍵字,它的值通常根據呼叫方式決定。箭頭函式例外,它在定義時就繼承外層的 this。

判斷 this 的 簡易版

  • 箭頭函式 → 定義時繼承外層 this
  • 普通函式 → 呼叫時決定 this
  • 物件呼叫 ➔ 指向物件
  • 直接呼叫 ➔ window / undefined(看嚴格模式)

🧭 this 的指向規則總覽

呼叫方式/情境 this 指向(在瀏覽器中) 備註
全域(非嚴格模式) window Node.js 中為 global
全域(嚴格模式) undefined
函式直接呼叫 window(非嚴格) / undefined(嚴格)
物件方法呼叫 呼叫該方法的物件 例如 obj.method()
constructor 中 (new) 新建立的實體物件 this 指向 new 出來的物件
class 中的 method 該 class 實體 類似一般物件的行為
callback 函式(一般函式) window(非嚴格) / undefined(嚴格) 例如:[1,2,3].forEach(function(){})
setTimeout/setInterval window Node.js 中為 Timeout(但非預期)
IIFE(立即執行函式) window(非嚴格) / undefined(嚴格)

箭頭函式 this 行為

箭頭函式永遠不會自己創造 this,它只會繼承「定義當下」的外層 this

箭頭函式的 this 行為總表

定義位置 / 外層 this 箭頭函式的 this 指向(在瀏覽器中) 備註
全域 window 若在全域中定義箭頭函式
class 中的 method 該 class 實體 this 繼承外層 class context,例如 constructor 中定義箭頭函式
setTimeout / setInterval 中定義 外層 this 例如在物件內使用箭頭函式當定時器 callback,會指向物件本身
callback 函式 外層 this 常見於 class 或物件中使用 forEach 來處理資料時
IIFE(立即執行函式) 外層 this 箭頭函式沒有自己的作用域,直接吃外面那層

🧠 箭頭函式的 this 核心原則:
箭頭函式永遠不會自己創造 this,它只會繼承「定義當下」的外層 this

this 的指向例子

🔸 1. 全域環境下的 this

var myName = "小明";
console.log(this === window); // true(在瀏覽器中)
console.log(this.myName);     // "小明"

🔸 2. 嚴格模式下的 this

"use strict";
var myName = "小明";
function fn() {
  console.log(this); // undefined
}
fn();

🔸 3. 純函式呼叫(非物件)

var myName = "小明";
function sayName() {
  console.log(this);        // window(非嚴格)
  console.log(this.myName); // "小明"
}
sayName();

🔸 4. 立即執行函式(IIFE)

var myName = "小明";
(function () {
  console.log(this); // window(非嚴格)
})();

(() => {
  console.log(this); // window,箭頭函式繼承外層的 this
})();

🔸 5. 作為物件方法呼叫

const family = {
  myName: "小明家",
  callName() {
    console.log(this.myName); // "小明家"
  },
};

family.callName();

🔸 6. 物件方法呼叫

const family = {
  myName: "小明家",
  ming: {
    myName: "小明",
    callName() {
      console.log(this.myName); // "小明"
    },
  },
};

family.ming.callName();

🔸 7. class 中的 this 及constructor 中 (new)

class Person {
  constructor(name) {
    this.name = name; 
    console.log(this);// this 指向 new 出來的物件
  }

  sayHi() {
    console.log("Hi, I am", this.name); // this 指向呼叫 sayHi() 的實例物件
  }
}

const p1 = new Person("小明");
p1.sayHi(); // this === p1 → "Hi, I am 小明"

🔸 8. callback 中的 this(普通函式)

[1, 2, 3].forEach(function () {
  console.log(this); // window(非嚴格)
});
  • 嚴格模式下
"use strict";

const arr = [1, 2, 3];

arr.forEach(function (item) {
  console.log(this); // ❗️在嚴格模式下,這裡的 this 是 undefined
});

🔸 9. setTimeout 中的 this

🔹 普通函式寫法(需要保存 this)

const component = {
  text: "Hello",
  getData() {
    const that = this;
    setTimeout(function () {
      that.text = "Hi";
      console.log(that.text); // "Hi"
    });
  },
};

component.getData();

🔹 箭頭函式寫法(自動繼承外層 this)

const person = {
  name: "小明",
  sayHi() {
    setTimeout(() => {
      console.log(this.name); // "小明"
    }, 1000);
  },
};

person.sayHi();

🔸 10. 箭頭函式的 this(沒有自己的 this)

window.myName = "全域的小明";

const family = {
  myName: "小明家",
  callName: () => {
    console.log(this.myName); // "全域的小明"(繼承外層的 this = window)
  },
};

family.callName();

🔸 11. 箭頭函式 + 一般方法包住

window.myName = "全域的小明";

const family = {
  myName: "小明家",
  callName: function () {
    (() => {
      console.log(this.myName); // "小明家"
    })();
  },
};

family.callName();

🔸 12. 展開運算子 (...) 與 this 的共享

  • ...component 是淺拷貝
  • getData/render/init 等 function 共用同一份參考
const component = {
  text: "預設文字",
  el: document.getElementById("root"),
  getData() {
    const that = this;
    setTimeout(function () {
      that.text = "已更新";
      that.render();
    });
  },
  init() {
    this.getData();
  },
  render() {
    this.el.innerText = this.text;
  },
};


const component2 = {
  ...component,
  el: document.getElementById("root2"),
};

component.init();
component2.init();


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言